package com.zc.standalone.configuration.protocol;

import com.ruoyi.common.config.RuoYiConfig;
import lombok.Generated;
import lombok.extern.slf4j.Slf4j;
import com.zc.web.bean.FastBeanCopier;
import com.zc.core.ProtocolSupport;
import com.zc.core.spi.ServiceContext;
import com.zc.supports.protocol.management.ProtocolSupportDefinition;
import com.zc.supports.protocol.management.jar.JarProtocolSupportLoader;
import com.zc.supports.protocol.management.jar.ProtocolClassLoader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

import javax.annotation.PreDestroy;
import java.io.File;
import java.util.Map;
/**
 * 自动下载并缓存协议包，
 * <pre>
 *     1. 下载的协议包报错在./data/protocols目录下，可通过启动参数-Djetlinks.protocol.temp.path进行配置
 *     2. 文件名规则: 协议ID+"_"+md5(文件地址)
 *     3. 如果文件不存在则下载协议
 * </pre>
 *
 * @author zhouhao
 * @since 1.3
 */
@Component
@Slf4j
public class AutoDownloadJarProtocolSupportLoader extends JarProtocolSupportLoader {
    
    @Override
    @Autowired
    @Generated
    public void setServiceContext(ServiceContext serviceContext) {
        super.setServiceContext(serviceContext);
    }

    @Override
    @PreDestroy
    @Generated
    protected void closeAll() {
        super.closeAll();
    }

    @Override
    protected void closeLoader(ProtocolClassLoader loader) {
        super.closeLoader(loader);
    }

    @Override
    public Mono<? extends ProtocolSupport> load(ProtocolSupportDefinition definition) {

        //复制新的配置信息
        ProtocolSupportDefinition newDef = FastBeanCopier.copy(definition, new ProtocolSupportDefinition());

        Map<String, Object> config = newDef.getConfiguration();

        String location = (String) config.getOrDefault("location", null);
        if (!StringUtils.hasText(location)) {
            return Mono.error(new IllegalArgumentException("location can not be empty"));
        }

        return loadFromFileManager(location)
            .flatMap(file -> {
                config.put("location", file.getAbsolutePath());
                return super
                    .load(newDef)
                    .subscribeOn(Schedulers.boundedElastic())
                    //加载失败则删除文件,防止文件内容错误时,一直无法加载
                    .doOnError(err -> file.delete());
            });

    }

    private Mono<File> loadFromFileManager(String location) {
        return Mono.just(new File(RuoYiConfig.getProtocolPath() + location));
    }

}
